////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                                                            //
//                                                         WNProject                                                          //
//                                                                                                                            //
//         This file is distributed under the BSD 2-Clause open source license. See Licenses/License.txt for details.         //
//                                                                                                                            //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#include "WNCore/inc/WNTypes.h"
#include "WNCore/inc/WNAssert.h"
#include "WNCore/inc/WNMacros.h"
#include "WNMemory/inc/WNMemory.h"
#include "WNStrings/inc/WNStrings.h"
#include "WNScripting/inc/WNScriptingEngine.h"
#include "WNScripting/inc/WNScriptingEngineFactory.h"
#include "WNScripting/inc/WNParameter.h"
#include <iostream>

#include "WNLogging/inc/WNBufferLogger.h"
#include "WNLogging/inc/WNConsoleLogger.h"
#include "WNLogging/inc/WNFileLogger.h"


using namespace WNStrings;
using namespace WNMemory;

WNLogging::WNDefaultLogParameters<WNLogging::eLogMax, 1024, true> mParams;
WNLogging::WNConsoleLogger<> mConsoleLogger;
static WNLogging::WNLog mMyLog(&mConsoleLogger, mParams);

WN_CHAR* getLine(WN_CHAR*_line, WN_UINT32 _sz){
   if (fgets(_line, _sz, stdin)) {
      WN_CHAR *current = WNStrChr(_line, '\n'); /* check for trailing '\n' */

      if (current != WN_NULL) {
         *current = '\0'; /* overwrite the '\n' with a terminating null */
      }
   }

   return(_line);
}

WN_INT32 testFunc(WN_UINT32 val) {
    WN_PRINTF("\n\n\n%d\n\n\n", val);

    return(1);
}

WN_VOID* sneakymalloc(WN_SIZE_T _sz) {
    WN_VOID* memory = WNMalloc(_sz);

    WN_PRINTF("malloc(%p)%ld\n", memory, _sz);

    return(memory);
}

WN_VOID sneakydelete(WN_VOID* _ptr) {
    WN_PRINTF("free(%p)\n", _ptr);

    WNFree(_ptr);
}

WN_INT32 get23() {
    return(23);
}

WN_INT32 add(WN_INT32 x, WN_INT32 y) {
    return(x + y);
}

WN_VOID print(WN_INT32 _val) {
    printf("%d\n", _val);
}

WN_INT32 main(WN_INT32 _argc, WN_CHAR** _argv) {
    WN_CHAR tests[1024];

    if (_argc < 2) {
        WN_PRINTF("Enter Filename >>");

        getLine(tests, 1023);

        return(-1);
    } else {
        WNStrCpy(tests, _argv[1]);
    }

    const WN_CHAR* func = (_argc > 2) ? _argv[2] : "test";
    const WN_CHAR* func2 = "test2";
    
    WNScripting::WNScriptingEngine* scriptingEngine = WNScripting::WNScriptingEngineFactory::CreateScriptingEngine();
    scriptingEngine->SetCompilationLog(&mMyLog);
    scriptingEngine->SetLogLevel(WNLogging::eLogMax);
    scriptingEngine->SetInternalLogLevel(WNLogging::eLogMax);
    WN_RELEASE_ASSERT(scriptingEngine->Initialize() == eWNOK);
    scriptingEngine->RegisterCFunction("get23", &get23);
    scriptingEngine->RegisterCFunction("add", &add);
    scriptingEngine->RegisterCFunction("printInt", &print);

    WN_INT32(*ret)(WN_INT32,WN_INT32) = NULL;
    WN_INT32(*ret2)() = NULL;
    
    if(eWNOK == scriptingEngine->GetPointerToFunction(tests,  func, ret)) {
        WN_INT32 iVal = ret(32, 2);
        std::cout << iVal << std::endl;
    }
    
    if(eWNOK == scriptingEngine->GetPointerToFunction(tests, func2, ret2)) {
        std::cout << ret2() << std::endl;
    }

    WN_DELETE(scriptingEngine);
    return(0);
}
